package com.duomi88.nettybio;

import java.util.UUID;

import org.apache.log4j.Logger;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
/**
 * netty 客户端
 *  公众号 duomi88
 */
public class NettyClient {
	
	private EventLoopGroup eventLoopGroup;
	
	private ChannelFuture client ;//客户端连接
	
	private static Logger LOG  = Logger.getLogger(NettyClient.class);
	
	public static void main(String[] args) {
		new NettyClient().sendMsg("127.0.0.1", SocketServer.PORT, "你好，服务器,请及时返回...");
	}
	/**
	 * 发送消息
	 * @param msg
	 */
	public void sendMsg(String ip,int port,String msg) {
		try {
			
			//1 连接到服务端，如果长连接可以修改此逻辑
			connectToServer(ip, port);
			//2生成阻塞计数器
			String sn = UUID.randomUUID().toString();
			Receiver.addWait(sn);
			
			//3 发送数据
			client.channel().writeAndFlush(sn+"@"+msg+"END").sync();//加end防止粘包
			LOG.info("发送消息成功,msg:"+msg);
			
			//4 等待接接收到消息后，计数器countdown。
			Receiver.block(sn);//可以设置等待时间，以防止线程长时间阻塞。
			//5处理服务端返回
			handlerServerAnswer(sn);
			
		} catch (Exception e) {
			LOG.error("处理消息失败.",e);
		}
	}
	private void handlerServerAnswer(String sn) {
		LOG.info("收到服务端返回，开始处理后续业务逻辑,返回消息为:"+Receiver.getResponse(sn));
	}
	/**
	 * 连接到服务端
	 * @param ip
	 * @param port
	 */
	public void connectToServer(String ip,int port) {
		try {
		
			this.eventLoopGroup = new NioEventLoopGroup();
			Bootstrap bootstrap = new Bootstrap();
			bootstrap.group(eventLoopGroup)
			.channel(NioSocketChannel.class)
			.option(ChannelOption.TCP_NODELAY,true).option(ChannelOption.SO_BACKLOG, 128)
			.handler(new ChannelInitializer<SocketChannel>() {
				@Override
				protected void initChannel(SocketChannel ch) throws Exception {
					ch.pipeline().addLast(new StringEncoder());
					ch.pipeline().addLast(new StringDecoder());
					ch.pipeline().addLast(new Receiver());
				}
			});
			this.client = bootstrap.connect(ip, port).sync();
			LOG.info("连接到服务端："+ip+":"+port);
		} catch (Exception e) {
			LOG.error("连接服务端"+ip+":"+port+"失败！");
		}
	}

}
